#! /usr/bin/env python2.6
"""This file is part of PyEllips.

    PyEllips is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PyEllips is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PyEllips.  If not, see <http://www.gnu.org/licenses/>."""
    
from Tkinter import *
import tkMessageBox
import numpy as np
import scipy 
#import fresnel 
import mccrackin
import matplotlib.pyplot as plt
import u3



def round_to_n(x, n):
 	if n < 1:
 		raise ValueError("number of significant digits must be >= 1")
 	# Use %e format to get the n most significant digits, as a string.
 	format = "%." + str(n-1) + "e"
 	as_string = format % x
 	return float(as_string)
 	
class GUIFramework(Frame):
    """This is the GUI"""
    
    def __init__(self,master=None):
        """Initialize yourself"""
        
        """Initialise the base class"""
        Frame.__init__(self,master)
        
        """Set the Window Title"""
        self.master.title("Ellipsometry")
        
        """Display the main window"
        with a little bit of padding"""
        self.grid(padx=10,pady=10)
        self.CreateWidgets()
       
    def CreateWidgets(self):
        """Create all the widgets that we need"""
                
        """Create the Text"""
        self.lb1Text = Label(self, text="Enter Psi (degrees):")
        self.lb1Text.grid(row=0, column=0)
        
        """Create the Entry, set it to be a bit wider"""
        self.PsiText = Entry(self)
        self.PsiText.grid(row=0, column=1, columnspan=2)
        
        """Create the Button, set the text and the 
        command that will be called when the button is clicked"""
        self.btnCalc = Button(self, text="Calc n,d!", command=self.Display)
        self.btnCalc.grid(row=0, column=4)
        
        self.btnCalcpd = Button(self, text="Calc psi delta", command=self.PsiDelta)
        self.btnCalcpd.grid(row=1, column=4)
        
        
        self.lb2Text = Label(self, text="Enter Delta (degrees):")
        self.lb2Text.grid(row=1, column=0)
        
        """Create the Entry, set it to be a bit wider"""
        self.DelText = Entry(self)
        self.DelText.grid(row=1, column=1, columnspan=2)
        self.lbwave=Label(self,text="Wavelength(A)")
        self.lbwave.grid(row=2,column=0)
        self.wavelength=Entry(self)
        self.wavelength.grid(row=2,column=1, columnspan=1)
        self.wavelength.insert(0,"6333")
        #now add substrate parameters
        self.lbsubs=Label(self,text="Substrate parameters:")
        self.lbsubs.grid(row=3,column=0)
        self.subsn=Entry(self)
        self.subsn.grid(row=3,column=2)
        self.lbsubsn=Label(self,text="n")
        self.lbsubsn.grid(row=3,column=1)
        self.lbsubsk=Label(self,text="k")
        self.lbsubsk.grid(row=3,column=3)
        self.subsk=Entry(self)
        self.subsk.grid(row=3,column=4)
        
        self.subsn.insert(0,"3.85")
        self.subsk.insert(0,"-0.02")
        
        #incident angle
        self.lbangle=Label(self,text="Incident angle (degrees):")
        self.lbangle.grid(row=4,column=0)
        self.angleText=Entry(self)
        self.angleText.grid(row=4,column=2)
        
        self.angleText.insert(0,"70")
        
        #film parameters
        self.lbfilm=Label(self,text="film parameters:")
        self.lbfilm.grid(row=6,column=0)
        self.filmn=Entry(self)
        self.filmn.grid(row=6,column=1,columnspan=1)
        self.filmn.insert(0,"1.5")
        self.filmd=Entry(self)
        self.filmd.grid(row=6,column=2,columnspan=1)
        self.filmd.insert(0,"100")
        
        #measurement section
        self.lbmeas=Label(self,text="measure film")
        self.lbmeas.grid(row=9,column=1, columnspan=1)
        self.btnStart = Button(self, text="Start", command=self.Measure)
        self.btnStart.grid(row=9, column=2)
        self.lbdmeas=Label(self,text="degrees/reading")
        self.lbdmeas.grid(row=9,column=3, columnspan=1)
        self.dmeas=Entry(self)
        self.dmeas.grid(row=9, column=4)
        self.dmeas.insert(0,"10")
        
        
        
    def Display(self):
        """Called when btnCalc is clicked, displays the contents of self.enText"""
        psi=float(self.PsiText.get())
        delta=float(self.DelText.get())
        sum=psi+delta
        """tkMessageBox.showinfo("Text", "You typed: %s and %s" % (self.PsiText.get(),self.DelText.get()))    """
        #tkMessageBox.showinfo("Text", " %f + %f=%f" % (psi,delta,sum))
        """ set up an ellipsometer instance"""
	ellips = mccrackin.Ellipsometer(np.float32(self.angleText.get()),np.float32(self.wavelength.get()),np.float32(self.subsn.get()),np.float32(self.subsk.get()))
        #sum=psi+delta    
        #tkMessageBox.showinfo("Text", " %f + %f=%f" % (psi,delta,sum))  
        #tkMessageBox.showinfo("Text", " answer %f and %f" % (ellips.find_nd(1.1,2.1,psi,delta)))
        nd=ellips.find_nd(1.1,2.1,psi,delta)
        #rndn=self.round_to_n(nd[0].real,4)
        self.filmn.delete(0, END)
        self.filmd.delete(0, END)
        self.filmn.insert(0,round_to_n(nd[0].real,4))
        self.filmd.insert(0,round_to_n(nd[1].real,4))
        
    def PsiDelta(self):
    	"""Called when btnpd is clicked, displays calculated psi and delta"""
        n=float(self.filmn.get())
        d=float(self.filmd.get())
        ellips = mccrackin.Ellipsometer(np.float32(self.angleText.get()),np.float32(self.wavelength.get()),np.float32(self.subsn.get()),np.float32(self.subsk.get()))
        #tkMessageBox.showinfo("Text", " answer %f and %f" % (ellips.calcpsiDelta(n,d)))
        psidel=ellips.calcpsiDelta(n,d)
        print psidel[0].real
        self.PsiText.delete(0, END)
        self.DelText.delete(0, END)
        self.PsiText.insert(0,round_to_n(psidel[0].real,4))
        self.DelText.insert(0,round_to_n(psidel[1].real,4))
        
    def Measure(self):
    #measure the ellipsometer voltages
    #uses LaJack u3
    	LJ=u3.U3()
    	AIN0_REGISTER = 0
    	# first get dark voltage
    	kMessageBox.showinfo("Text", "Cover detector input and press Return")
    	DarkV=LJ.readRegister(AIN0_REGISTER)
    	#now work out how many steps
    	nsteps=int(360./np.float32(self.dmeas.get()))
    	print nsteps
    	angle=np.arange(0, 360, int(np.float32(self.dmeas.get())))
    	reading=np.zeros(nsteps)
    	k0=0
    	k1=0
    	k2=0
    	for n in range(0, nsteps,1):
    		
    		tkMessageBox.showinfo("Text", "Set ellipsometer to %f" % angle[n])
    		reading[n]=LJ.readRegister(AIN0_REGISTER)-DarkV
    		k1+=reading[n]*scipy.cos(2*np.pi*angle[n]/180.0)
    		k2+=reading[n]*scipy.sin(2*np.pi*angle[n]/180.0)
    	k0=scipy.sum(reading)/nsteps 
    	k1=2.*k1/nsteps
    	k2=2.0*k2/nsteps
    	# Now calculate Psi and Delta
    	psi=scipy.arctan(scipy.sqrt((k0+k1)/(k0-k1)))
    	delta=scipy.arccos(k2/(scipy.sqrt(k0*k0-k1*k1)))
    	self.PsiText.delete(0, END)
        self.DelText.delete(0, END)
        self.PsiText.insert(0,180.*psi/np.pi)
        self.DelText.insert(0,delta*180./np.pi)
        plot=plt.plot(angle, reading, 'ro')
		#plot.axis([0, 6, 0, 20])
		LJ=0
		
    def round_to_n(self,x, n):
    	if n < 1:
        	raise ValueError("number of significant digits must be >= 1")
    		return "%.*e" % (n-1, x)
    
        
if __name__ == "__main__":
    guiFrame = GUIFramework()
    guiFrame.mainloop()
    